﻿using System;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Win32;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using NetPrintShare;
using System.Net.NetworkInformation;
using System.Net;

public class ServiceManager
{
    public static void InstallService(string printName, int port)
    {
        string exePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
        if (printName.Contains(" "))
        {
            // 替换空格为下划线
            printName = printName.Replace(" ", "_");
        }
        Console.WriteLine($"安装路径: {exePath}");
        Console.WriteLine($"打印机名称: {printName}");
        Console.WriteLine($"端口号: {port}");

        string serviceName = "网络打印服务_" + printName + "_" + port;
        // 检查服务名是否已存在
        if (ServiceExists(serviceName))
        {
            Console.WriteLine($"服务名 {serviceName} 已存在，无法安装。");
            return;
        }

        // 检查端口是否已被使用
        if (PortInUse(port))
        {
            Console.WriteLine($"端口 {port} 已被其他服务使用，无法安装。");
            return;
        }

        IntPtr scm = OpenSCManager(null, null, 0x0002); // SC_MANAGER_CREATE_SERVICE
        if (scm == IntPtr.Zero)
        {
            Console.WriteLine("无法打开服务控制管理器");
            return;
        }

        IntPtr service = CreateService(
            scm,
            serviceName,
            serviceName,
            0xF01FF, // SERVICE_ALL_ACCESS
            0x00000010, // SERVICE_WIN32_OWN_PROCESS
            0x00000002, // SERVICE_AUTO_START
            0x00000001, // SERVICE_ERROR_NORMAL
            $"\"{exePath}\" {printName} {port}", // 确保端口号作为参数传递
            null, (IntPtr)null, null, null, null);

        if (service == IntPtr.Zero)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Program.LogMessage("无法创建服务，可能有相同端口的服务已经存在！");
            Console.ResetColor();
        }
        else
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("服务安装成功");
            Console.ResetColor();

            // 设置服务描述
            SERVICE_DESCRIPTION sd = new SERVICE_DESCRIPTION();
            sd.lpDescription = $"这是一个网络打印服务，将网络打印请求从端口{port}转发到本地打印机{printName}进行打印";
            if (!ChangeServiceConfig2(service, 1, ref sd)) // 1 是 SERVICE_CONFIG_DESCRIPTION
            {
                Console.WriteLine("无法设置服务描述");
            }

            // 尝试启动服务
            if (StartService(service, 0, null))
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Program.LogMessage("服务启动成功！");
                Console.ResetColor();
            }
            else
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Program.LogMessage("服务启动失败！");
                Console.ResetColor();
            }

            // 将端口号写入注册表
            using (RegistryKey key = Registry.LocalMachine.CreateSubKey(@"SYSTEM\CurrentControlSet\Services\" + serviceName))
            {
                if (key != null)
                {
                    key.SetValue("Port", port);
                }
            }
        }

        CloseServiceHandle(service);
        CloseServiceHandle(scm);
    }

    public static void UninstallService(int port)
    {
        string portSuffix = "_" + port;
        string serviceNameToDelete = null;

        // 使用 WMI 枚举所有服务
        ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Service");
        foreach (ManagementObject currentService in searcher.Get())
        {
            string serviceName = currentService["Name"]?.ToString();
            if (serviceName != null && serviceName.EndsWith(portSuffix))
            {
                serviceNameToDelete = serviceName;
                break;
            }
        }

        if (serviceNameToDelete == null)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine($"未找到以端口号 {port} 结尾的服务");
            Console.ResetColor();
            return;
        }

        IntPtr scm = OpenSCManager(null, null, 0x0001); // SC_MANAGER_CONNECT
        if (scm == IntPtr.Zero)
        {
            Console.WriteLine("无法打开服务控制管理器");
            return;
        }

        IntPtr service = OpenService(scm, serviceNameToDelete, 0x0020 | 0x00010000 | 0x0004); // SERVICE_QUERY_STATUS | DELETE | SERVICE_STOP
        if (service == IntPtr.Zero)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine($"无法打开服务: {serviceNameToDelete},可能当前非管理员模式运行！");
            Console.ResetColor();
        }
        else
        {
            // 检查服务状态
            SERVICE_STATUS status = new SERVICE_STATUS();
            if (QueryServiceStatus(service, ref status))
            {
                if (status.dwCurrentState != 0x00000001) // SERVICE_STOPPED
                {
                    // 停止服务
                    Console.WriteLine($"正在停止服务: {serviceNameToDelete}");
                    ControlService(service, 0x00000001, ref status); // SERVICE_CONTROL_STOP

                    // 等待服务停止
                    while (status.dwCurrentState != 0x00000001) // SERVICE_STOPPED
                    {
                        Console.WriteLine($"等待服务停止: {serviceNameToDelete} 当前状态: {status.dwCurrentState}");
                        Thread.Sleep(1000); // 等待一秒
                        QueryServiceStatus(service, ref status);
                    }
                    Console.WriteLine($"服务 {serviceNameToDelete} 已停止");
                }
            }

            // 删除服务
            if (DeleteService(service))
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Program.LogMessage($"服务 {serviceNameToDelete} 卸载成功");
                Console.ResetColor();
            }
            else
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Program.LogMessage($"服务 {serviceNameToDelete} 卸载失败");
                Console.ResetColor();
            }
        }

        CloseServiceHandle(service);
        CloseServiceHandle(scm);
    }

    public static List<string> GetNetworkPrinterServices()
    {
        List<string> serviceNames = new List<string>();
        string serviceNamePrefix = "网络打印服务_";

        // 使用 WMI 枚举所有服务
        ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Service");
        foreach (ManagementObject currentService in searcher.Get())
        {
            string serviceName = currentService["Name"]?.ToString();
            if (serviceName != null && serviceName.StartsWith(serviceNamePrefix))
            {
                serviceNames.Add(serviceName);
            }
        }

        // 输出所有找到的服务名称
        if (serviceNames.Count > 0)
        {
            Console.WriteLine("\n");
            Console.WriteLine("当前已安装的打印机服务列表:\n");
            foreach (var name in serviceNames)
            {
                // 去掉前缀
                string trimmedName = name.Substring(serviceNamePrefix.Length);

                // 找到最后一个下划线的位置
                int lastUnderscoreIndex = trimmedName.LastIndexOf('_');

                if (lastUnderscoreIndex != -1)
                {
                    // 提取打印机名称和端口号
                    string printerName = trimmedName.Substring(0, lastUnderscoreIndex);
                    string port = trimmedName.Substring(lastUnderscoreIndex + 1);

                    // 获取服务状态
                    string query = $"SELECT * FROM Win32_Service WHERE Name = '{name}'";
                    ManagementObjectSearcher statusSearcher = new ManagementObjectSearcher(query);
                    string status = "未知";
                    foreach (ManagementObject service in statusSearcher.Get())
                    {
                        status = service["State"]?.ToString() ?? "未知";
                    }
                    // 将状态转换为中文
                    string statusInChinese;
                    switch (status)
                    {
                        case "Running":
                            statusInChinese = "运行中";
                            Console.ForegroundColor = ConsoleColor.Green;
                            break;
                        case "Stopped":
                            statusInChinese = "已停止";
                            Console.ForegroundColor = ConsoleColor.Red;
                            break;
                        case "Paused":
                            statusInChinese = "已暂停";
                            Console.ForegroundColor = ConsoleColor.Yellow;
                            break;
                        case "Start Pending":
                            statusInChinese = "启动中";
                            Console.ForegroundColor = ConsoleColor.Cyan;
                            break;
                        case "Stop Pending":
                            statusInChinese = "停止中";
                            Console.ForegroundColor = ConsoleColor.Magenta;
                            break;
                        case "Continue Pending":
                            statusInChinese = "继续中";
                            Console.ForegroundColor = ConsoleColor.Blue;
                            break;
                        case "Pause Pending":
                            statusInChinese = "暂停中";
                            Console.ForegroundColor = ConsoleColor.DarkYellow;
                            break;
                        default:
                            statusInChinese = "未知";
                            Console.ForegroundColor = ConsoleColor.Gray;
                            break;
                    }

                    Console.Write($"打印机: {printerName} | 端口: {port} | 服务状态: {statusInChinese}\n\n");
                    Console.ResetColor(); // 重置颜色
                }
            }
        }
        else
        {
            Console.WriteLine("没有找到符合前缀的服务。");
        }

        return serviceNames;
    }

    // P/Invoke declarations
    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern IntPtr OpenSCManager(string lpMachineName, string lpDatabaseName, uint dwDesiredAccess);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern IntPtr CreateService(
        IntPtr hSCManager,
        string lpServiceName,
        string lpDisplayName,
        uint dwDesiredAccess,
        uint dwServiceType,
        uint dwStartType,
        uint dwErrorControl,
        string lpBinaryPathName,
        string lpLoadOrderGroup,
        IntPtr lpdwTagId,
        string lpDependencies,
        string lpServiceStartName,
        string lpPassword);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool StartService(IntPtr hService, int dwNumServiceArgs, string[] lpServiceArgVectors);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool DeleteService(IntPtr hService);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool CloseServiceHandle(IntPtr hSCObject);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool QueryServiceStatus(IntPtr hService, ref SERVICE_STATUS lpServiceStatus);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool ControlService(IntPtr hService, uint dwControl, ref SERVICE_STATUS lpServiceStatus);

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern bool ChangeServiceConfig2(IntPtr hService, int dwInfoLevel, ref SERVICE_DESCRIPTION lpInfo);

    [StructLayout(LayoutKind.Sequential)]
    private struct SERVICE_STATUS
    {
        public uint dwServiceType;
        public uint dwCurrentState;
        public uint dwControlsAccepted;
        public uint dwWin32ExitCode;
        public uint dwServiceSpecificExitCode;
        public uint dwCheckPoint;
        public uint dwWaitHint;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    private struct SERVICE_DESCRIPTION
    {
        public string lpDescription;
    }

    // 检查服务是否存在
    private static bool ServiceExists(string serviceName)
    {
        IntPtr scm = OpenSCManager(null, null, 0x0001); // SC_MANAGER_CONNECT
        if (scm == IntPtr.Zero)
        {
            Console.WriteLine("无法打开服务控制管理器");
            return false;
        }

        IntPtr service = OpenService(scm, serviceName, 0x0001); // SERVICE_QUERY_STATUS
        if (service != IntPtr.Zero)
        {
            CloseServiceHandle(service);
            CloseServiceHandle(scm);
            return true;
        }

        CloseServiceHandle(scm);
        return false;
    }

    // 检查端口是否已被使用
    private static bool PortInUse(int port)
    {
        // 获取当前系统的IP全局属性
        IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();

        // 获取所有活动的TCP连接
        IPEndPoint[] tcpEndPoints = ipProperties.GetActiveTcpListeners();

        // 检查端口是否在活动的TCP连接中
        foreach (IPEndPoint endPoint in tcpEndPoints)
        {
            if (endPoint.Port == port)
            {
                return true; // 端口已被使用
            }
        }

        return false; // 端口未被使用
    }
}
